module OH_PAYLOAD_SCRAM(
   GLB_RESET,
 // CPU config signals
   CFG_POS_PAYLOAD_SCRAM_EN,
   CFG_POS_PAYLOAD_SCRAM_MODE,
   CFG_POS_PAYLOAD_SCRAM_RESTART,
 // input data bus, the data/data enable before descram
   CLOCK155M,
   DBIN_DATA,
   DBIN_DATA_EN,
 // ouptut data bus, the data/data enable after descram
   DBOUT_DATA,
   DBOUT_DATA_EN
   );

input                      GLB_RESET;                      // reset, '1' is effective
input                      CFG_POS_PAYLOAD_SCRAM_EN;       // CPU configuration signal, '1' enable the POS payload scram function
input                      CFG_POS_PAYLOAD_SCRAM_MODE;
input                      CFG_POS_PAYLOAD_SCRAM_RESTART;
input                      CLOCK155M;                      // input data bus clock at 156MHz, also used as module work clock
input[63:0]                DBIN_DATA;                      //
input                      DBIN_DATA_EN;                   //
output reg[63:0]           DBOUT_DATA;                     //
output reg                 DBOUT_DATA_EN;                  //

reg[63:0]                  NSCRM_DATA;
reg                        NSCRM_DATA_EN;

reg[42:0]                  X43_REMAINDER;
reg[63:0]                  X43_SCRM_DATA;
reg                        X43_SCRM_DATA_EN;
wire[63:0]                 X43_X;

reg                        DSEL_SCRAM_EN;
reg                        DSEL_SCRAM_MODE;
reg                        SCRAM_RESTART;

// X43+1 SCRAM Polygram, use input 64bits data as X[i] 0<=i<64; the remainder as R(i} 0<=i<43; the reusult after descram as Y(i) 0<=i<64
// R[0]=R[22]+X[0]+X[43]            R[1]=R[23]+X[1]+X[44]            R[2]=R[24]+X[2]+X[45]           R[3]=R[25]+X[3]+X[46]              R[4]=R[26]+X[4]+X[47]
// R[5]=R[27]+X[5]+X[48]            R[6]=R[28]+X[6]+X[49]            R[7]=R[29]+X[7]+X[50]           R[8]=R[30]+X[8]+X[51]              R[9]=R[31]+X[9]+X[52]
// R[10]=R[32]+X[10]+X[53]          R[11]=R[33]+X[11]+X[54]          R[12]=R[34]+X[12]+X[55]         R[13]=R[35]+X[13]+X[56]            R[14]=R[36]+X[14]+X[57]
// R[15]=R[37]+X[15]+X[58]          R[16]=R[38]+X[16]+X[59]          R[17]=R[39]+X[17]+X[60]         R[18]=R[40]+X[18]+X[61]            R[19]=R[41]+X[19]+X[62]
// R[20]=R[42]+X[20]+X[63]          R[21]=R[0]+X[21]                 R[22]=R[1]+X[22]                R[23]=R[2]+X[23]                   R[24]=R[3]+X[24]
// R[25]=R[4]+X[25]                 R[26]=R[5]+X[26]                 R[27]=R[6]+X[27]                R[28]=R[7]+X[28]                   R[29]=R[8]+X[29]
// R[30]=R[9]+X[30]                 R[31]=R[10]+X[31]                R[32]=R[11]+X[32]               R[33]=R[12]+X[33]                  R[34]=R[13]+X[34]
// R[35]=R[14]+X[35]                R[36]=R[15]+X[36]                R[37]=R[16]+X[37]               R[38]=R[17]+X[38]                  R[39]=R[18]+X[39]
// R[40]=R[19]+X[40]                R[41]=R[20]+X[41]                R[42]=R[21]+X[42]
// Y[0]=R[22]+X[0]+X[43]            Y[1]=R[23]+X[1]+X[44]            Y[2]=R[24]+X[2]+X[45]           Y[3]=R[25]+X[3]+X[46]              Y[4]=R[26]+X[4]+X[47]
// Y[5]=R[27]+X[5]+X[48]            Y[6]=R[28]+X[6]+X[49]            Y[7]=R[29]+X[7]+X[50]           Y[8]=R[30]+X[8]+X[51]              Y[9]=R[31]+X[9]+X[52]
// Y[10]=R[32]+X[10]+X[53]          Y[11]=R[33]+X[11]+X[54]          Y[12]=R[34]+X[12]+X[55]         Y[13]=R[35]+X[13]+X[56]            Y[14]=R[36]+X[14]+X[57]
// Y[15]=R[37]+X[15]+X[58]          Y[16]=R[38]+X[16]+X[59]          Y[17]=R[39]+X[17]+X[60]         Y[18]=R[40]+X[18]+X[61]            Y[19]=R[41]+X[19]+X[62]
// Y[20]=R[42]+X[20]+X[63]          Y[21]=R[0]+X[21]                 Y[22]=R[1]+X[22]                Y[23]=R[2]+X[23]                   Y[24]=R[3]+X[24]
// Y[25]=R[4]+X[25]                 Y[26]=R[5]+X[26]                 Y[27]=R[6]+X[27]                Y[28]=R[7]+X[28]                   Y[29]=R[8]+X[29]
// Y[30]=R[9]+X[30]                 Y[31]=R[10]+X[31]                Y[32]=R[11]+X[32]               Y[33]=R[12]+X[33]                  Y[34]=R[13]+X[34]
// Y[35]=R[14]+X[35]                Y[36]=R[15]+X[36]                Y[37]=R[16]+X[37]               Y[38]=R[17]+X[38]                  Y[39]=R[18]+X[39]
// Y[40]=R[19]+X[40]                Y[41]=R[20]+X[41]                Y[42]=R[21]+X[42]               Y[43]=R[22]+X[43]                  Y[44]=R[23]+X[44]
// Y[45]=R[24]+X[45]                Y[46]=R[25]+X[46]                Y[47]=R[26]+X[47]               Y[48]=R[27]+X[48]                  Y[49]=R[28]+X[49]
// Y[50]=R[29]+X[50]                Y[51]=R[30]+X[51]                Y[52]=R[31]+X[52]               Y[53]=R[32]+X[53]                  Y[54]=R[33]+X[54]
// Y[55]=R[34]+X[55]                Y[56]=R[35]+X[56]                Y[57]=R[36]+X[57]               Y[58]=R[37]+X[58]                  Y[59]=R[38]+X[59]
// Y[60]=R[39]+X[60]                Y[61]=R[40]+X[61]                Y[62]=R[41]+X[62]               Y[63]=R[42]+X[63]


// clock in CFG_POS_PAYLOAD_SCRAM_RESTART with CLOCK155M
always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 )
      SCRAM_RESTART                      <= 1'b0;
   else
      SCRAM_RESTART                      <= CFG_POS_PAYLOAD_SCRAM_RESTART;
end


// X43+1 scram procedure
  assign X43_X[63:0]  =DBIN_DATA[63:0];

always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 )
      X43_REMAINDER[42:0]                <= 43'h7FF_FFFF_FFFF;
   else begin
      if ( SCRAM_RESTART==1'b1 ) begin
         X43_REMAINDER[42:0]             <= 43'h7FF_FFFF_FFFF;
      end
      else if ( DBIN_DATA_EN==1'b1 ) begin
         X43_REMAINDER[0]                <= X43_REMAINDER[22] ^ X43_X[0] ^ X43_X[43];
         X43_REMAINDER[1]                <= X43_REMAINDER[23] ^ X43_X[1] ^ X43_X[44];
         X43_REMAINDER[2]                <= X43_REMAINDER[24] ^ X43_X[2] ^ X43_X[45];
         X43_REMAINDER[3]                <= X43_REMAINDER[25] ^ X43_X[3] ^ X43_X[46];
         X43_REMAINDER[4]                <= X43_REMAINDER[26] ^ X43_X[4] ^ X43_X[47];
         X43_REMAINDER[5]                <= X43_REMAINDER[27] ^ X43_X[5] ^ X43_X[48];
         X43_REMAINDER[6]                <= X43_REMAINDER[28] ^ X43_X[6] ^ X43_X[49];
         X43_REMAINDER[7]                <= X43_REMAINDER[29] ^ X43_X[7] ^ X43_X[50];
         X43_REMAINDER[8]                <= X43_REMAINDER[30] ^ X43_X[8] ^ X43_X[51];
         X43_REMAINDER[9]                <= X43_REMAINDER[31] ^ X43_X[9] ^ X43_X[52];
         X43_REMAINDER[10]               <= X43_REMAINDER[32] ^ X43_X[10] ^ X43_X[53];
         X43_REMAINDER[11]               <= X43_REMAINDER[33] ^ X43_X[11] ^ X43_X[54];
         X43_REMAINDER[12]               <= X43_REMAINDER[34] ^ X43_X[12] ^ X43_X[55];
         X43_REMAINDER[13]               <= X43_REMAINDER[35] ^ X43_X[13] ^ X43_X[56];
         X43_REMAINDER[14]               <= X43_REMAINDER[36] ^ X43_X[14] ^ X43_X[57];
         X43_REMAINDER[15]               <= X43_REMAINDER[37] ^ X43_X[15] ^ X43_X[58];
         X43_REMAINDER[16]               <= X43_REMAINDER[38] ^ X43_X[16] ^ X43_X[59];
         X43_REMAINDER[17]               <= X43_REMAINDER[39] ^ X43_X[17] ^ X43_X[60];
         X43_REMAINDER[18]               <= X43_REMAINDER[40] ^ X43_X[18] ^ X43_X[61];
         X43_REMAINDER[19]               <= X43_REMAINDER[41] ^ X43_X[19] ^ X43_X[62];
         X43_REMAINDER[20]               <= X43_REMAINDER[42] ^ X43_X[20] ^ X43_X[63];
         X43_REMAINDER[21]               <= X43_REMAINDER[0] ^ X43_X[21];
         X43_REMAINDER[22]               <= X43_REMAINDER[1] ^ X43_X[22];
         X43_REMAINDER[23]               <= X43_REMAINDER[2] ^ X43_X[23];
         X43_REMAINDER[24]               <= X43_REMAINDER[3] ^ X43_X[24];
         X43_REMAINDER[25]               <= X43_REMAINDER[4] ^ X43_X[25];
         X43_REMAINDER[26]               <= X43_REMAINDER[5] ^ X43_X[26];
         X43_REMAINDER[27]               <= X43_REMAINDER[6] ^ X43_X[27];
         X43_REMAINDER[28]               <= X43_REMAINDER[7] ^ X43_X[28];
         X43_REMAINDER[29]               <= X43_REMAINDER[8] ^ X43_X[29];
         X43_REMAINDER[30]               <= X43_REMAINDER[9] ^ X43_X[30];
         X43_REMAINDER[31]               <= X43_REMAINDER[10] ^ X43_X[31];
         X43_REMAINDER[32]               <= X43_REMAINDER[11] ^ X43_X[32];
         X43_REMAINDER[33]               <= X43_REMAINDER[12] ^ X43_X[33];
         X43_REMAINDER[34]               <= X43_REMAINDER[13] ^ X43_X[34];
         X43_REMAINDER[35]               <= X43_REMAINDER[14] ^ X43_X[35];
         X43_REMAINDER[36]               <= X43_REMAINDER[15] ^ X43_X[36];
         X43_REMAINDER[37]               <= X43_REMAINDER[16] ^ X43_X[37];
         X43_REMAINDER[38]               <= X43_REMAINDER[17] ^ X43_X[38];
         X43_REMAINDER[39]               <= X43_REMAINDER[18] ^ X43_X[39];
         X43_REMAINDER[40]               <= X43_REMAINDER[19] ^ X43_X[40];
         X43_REMAINDER[41]               <= X43_REMAINDER[20] ^ X43_X[41];
         X43_REMAINDER[42]               <= X43_REMAINDER[21] ^ X43_X[42];
      end
   end
end
always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 )
      X43_SCRM_DATA[63:0]                <= 64'd0;
   else begin
      if ( DBIN_DATA_EN==1'b1 ) begin
         X43_SCRM_DATA[0]                <= X43_REMAINDER[22] ^ X43_X[0] ^ X43_X[43];
         X43_SCRM_DATA[1]                <= X43_REMAINDER[23] ^ X43_X[1] ^ X43_X[44];
         X43_SCRM_DATA[2]                <= X43_REMAINDER[24] ^ X43_X[2] ^ X43_X[45];
         X43_SCRM_DATA[3]                <= X43_REMAINDER[25] ^ X43_X[3] ^ X43_X[46];
         X43_SCRM_DATA[4]                <= X43_REMAINDER[26] ^ X43_X[4] ^ X43_X[47];
         X43_SCRM_DATA[5]                <= X43_REMAINDER[27] ^ X43_X[5] ^ X43_X[48];
         X43_SCRM_DATA[6]                <= X43_REMAINDER[28] ^ X43_X[6] ^ X43_X[49];
         X43_SCRM_DATA[7]                <= X43_REMAINDER[29] ^ X43_X[7] ^ X43_X[50];
         X43_SCRM_DATA[8]                <= X43_REMAINDER[30] ^ X43_X[8] ^ X43_X[51];
         X43_SCRM_DATA[9]                <= X43_REMAINDER[31] ^ X43_X[9] ^ X43_X[52];
         X43_SCRM_DATA[10]               <= X43_REMAINDER[32] ^ X43_X[10] ^ X43_X[53];
         X43_SCRM_DATA[11]               <= X43_REMAINDER[33] ^ X43_X[11] ^ X43_X[54];
         X43_SCRM_DATA[12]               <= X43_REMAINDER[34] ^ X43_X[12] ^ X43_X[55];
         X43_SCRM_DATA[13]               <= X43_REMAINDER[35] ^ X43_X[13] ^ X43_X[56];
         X43_SCRM_DATA[14]               <= X43_REMAINDER[36] ^ X43_X[14] ^ X43_X[57];
         X43_SCRM_DATA[15]               <= X43_REMAINDER[37] ^ X43_X[15] ^ X43_X[58];
         X43_SCRM_DATA[16]               <= X43_REMAINDER[38] ^ X43_X[16] ^ X43_X[59];
         X43_SCRM_DATA[17]               <= X43_REMAINDER[39] ^ X43_X[17] ^ X43_X[60];
         X43_SCRM_DATA[18]               <= X43_REMAINDER[40] ^ X43_X[18] ^ X43_X[61];
         X43_SCRM_DATA[19]               <= X43_REMAINDER[41] ^ X43_X[19] ^ X43_X[62];
         X43_SCRM_DATA[20]               <= X43_REMAINDER[42] ^ X43_X[20] ^ X43_X[63];
         X43_SCRM_DATA[21]               <= X43_REMAINDER[0] ^ X43_X[21];
         X43_SCRM_DATA[22]               <= X43_REMAINDER[1] ^ X43_X[22];
         X43_SCRM_DATA[23]               <= X43_REMAINDER[2] ^ X43_X[23];
         X43_SCRM_DATA[24]               <= X43_REMAINDER[3] ^ X43_X[24];
         X43_SCRM_DATA[25]               <= X43_REMAINDER[4] ^ X43_X[25];
         X43_SCRM_DATA[26]               <= X43_REMAINDER[5] ^ X43_X[26];
         X43_SCRM_DATA[27]               <= X43_REMAINDER[6] ^ X43_X[27];
         X43_SCRM_DATA[28]               <= X43_REMAINDER[7] ^ X43_X[28];
         X43_SCRM_DATA[29]               <= X43_REMAINDER[8] ^ X43_X[29];
         X43_SCRM_DATA[30]               <= X43_REMAINDER[9] ^ X43_X[30];
         X43_SCRM_DATA[31]               <= X43_REMAINDER[10] ^ X43_X[31];
         X43_SCRM_DATA[32]               <= X43_REMAINDER[11] ^ X43_X[32];
         X43_SCRM_DATA[33]               <= X43_REMAINDER[12] ^ X43_X[33];
         X43_SCRM_DATA[34]               <= X43_REMAINDER[13] ^ X43_X[34];
         X43_SCRM_DATA[35]               <= X43_REMAINDER[14] ^ X43_X[35];
         X43_SCRM_DATA[36]               <= X43_REMAINDER[15] ^ X43_X[36];
         X43_SCRM_DATA[37]               <= X43_REMAINDER[16] ^ X43_X[37];
         X43_SCRM_DATA[38]               <= X43_REMAINDER[17] ^ X43_X[38];
         X43_SCRM_DATA[39]               <= X43_REMAINDER[18] ^ X43_X[39];
         X43_SCRM_DATA[40]               <= X43_REMAINDER[19] ^ X43_X[40];
         X43_SCRM_DATA[41]               <= X43_REMAINDER[20] ^ X43_X[41];
         X43_SCRM_DATA[42]               <= X43_REMAINDER[21] ^ X43_X[42];
         X43_SCRM_DATA[43]               <= X43_REMAINDER[22] ^ X43_X[43];
         X43_SCRM_DATA[44]               <= X43_REMAINDER[23] ^ X43_X[44];
         X43_SCRM_DATA[45]               <= X43_REMAINDER[24] ^ X43_X[45];
         X43_SCRM_DATA[46]               <= X43_REMAINDER[25] ^ X43_X[46];
         X43_SCRM_DATA[47]               <= X43_REMAINDER[26] ^ X43_X[47];
         X43_SCRM_DATA[48]               <= X43_REMAINDER[27] ^ X43_X[48];
         X43_SCRM_DATA[49]               <= X43_REMAINDER[28] ^ X43_X[49];
         X43_SCRM_DATA[50]               <= X43_REMAINDER[29] ^ X43_X[50];
         X43_SCRM_DATA[51]               <= X43_REMAINDER[30] ^ X43_X[51];
         X43_SCRM_DATA[52]               <= X43_REMAINDER[31] ^ X43_X[52];
         X43_SCRM_DATA[53]               <= X43_REMAINDER[32] ^ X43_X[53];
         X43_SCRM_DATA[54]               <= X43_REMAINDER[33] ^ X43_X[54];
         X43_SCRM_DATA[55]               <= X43_REMAINDER[34] ^ X43_X[55];
         X43_SCRM_DATA[56]               <= X43_REMAINDER[35] ^ X43_X[56];
         X43_SCRM_DATA[57]               <= X43_REMAINDER[36] ^ X43_X[57];
         X43_SCRM_DATA[58]               <= X43_REMAINDER[37] ^ X43_X[58];
         X43_SCRM_DATA[59]               <= X43_REMAINDER[38] ^ X43_X[59];
         X43_SCRM_DATA[60]               <= X43_REMAINDER[39] ^ X43_X[60];
         X43_SCRM_DATA[61]               <= X43_REMAINDER[40] ^ X43_X[61];
         X43_SCRM_DATA[62]               <= X43_REMAINDER[41] ^ X43_X[62];
         X43_SCRM_DATA[63]               <= X43_REMAINDER[42] ^ X43_X[63];
      end
   end
end
always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 )
      X43_SCRM_DATA_EN                   <= 1'b0;
   else
      X43_SCRM_DATA_EN                   <= DBIN_DATA_EN;
end



// no scram precedure
always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 ) begin
      NSCRM_DATA[63:0]                   <= 64'd0;
      NSCRM_DATA_EN                      <= 1'b0;
   end
   else begin
      NSCRM_DATA[63:0]                   <= DBIN_DATA[63:0];
      NSCRM_DATA_EN                      <= DBIN_DATA_EN;
   end
end


// outut select with 
// clock in CPU control signal
always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 ) begin
      DSEL_SCRAM_EN                  <= 1'b0;
      DSEL_SCRAM_MODE                <= 1'b0;
   end
   else begin
      DSEL_SCRAM_EN                  <= CFG_POS_PAYLOAD_SCRAM_EN;
      DSEL_SCRAM_MODE                <= CFG_POS_PAYLOAD_SCRAM_MODE;
   end
end


always @( posedge GLB_RESET or posedge CLOCK155M ) begin
   if ( GLB_RESET==1'b1 ) begin
      DBOUT_DATA[63:0]               <= 64'd0;
      DBOUT_DATA_EN                  <= 1'b0;
   end
   else begin
      if ( DSEL_SCRAM_EN==1'b0 ) begin                         // no scram mode
         DBOUT_DATA[63:0]            <= NSCRM_DATA[63:0];
         DBOUT_DATA_EN               <= NSCRM_DATA_EN;
      end
      else begin
         if ( DSEL_SCRAM_MODE==1'b0 ) begin                    // X43+1 scram mode
            DBOUT_DATA[63:0]         <= X43_SCRM_DATA[63:0];
            DBOUT_DATA_EN            <= X43_SCRM_DATA_EN;
         end
         else begin                                            // others mode, default as no scram mode
            DBOUT_DATA[63:0]         <= NSCRM_DATA[63:0];
            DBOUT_DATA_EN            <= NSCRM_DATA_EN;
         end
      end
   end
end

endmodule 
